package main

import (
	"fmt"
	"math/rand"
	"time"
)

func main() {
	//testNoBuffer()
	//testNoBuffer01()
	//testNoBuffer02()
	//testNoBuffer03()
	//testNoBuffer04()
	testNoBuffer05()
	//testWithBuffer()

}

// testNoBuffer01
//
//	@Description: 无缓冲 channel 要求发送和接收同步,无缓冲 channel 用 goroutine 配对
//	fatal error: all goroutines are asleep - deadlock!
func testNoBuffer() {
	var ch chan int = make(chan int)
	now := time.Now()

	ch <- 1
	num := <-ch
	fmt.Println("num=", num, "time=", time.Since(now))
}

// testNoBuffer
//
//	@Description: 没有缓冲去的
func testNoBuffer01() {
	var ch chan int = make(chan int)
	now := time.Now()

	go func() {
		time.Sleep(time.Second * 2)
		ch <- rand.Intn(100)
	}()
	num := <-ch
	fmt.Println("num=", num, "time=", time.Since(now))
}

func testNoBuffer02() {
	var ch chan int = make(chan int)
	fmt.Printf("len=%d cap=%d\n", len(ch), cap(ch))
	now := time.Now()

	go func() {
		time.Sleep(time.Second * 2)
		for i := 0; i < 3; i++ {
			ch <- i
			fmt.Println("子协程send数据：", i)
			time.Sleep(time.Second * 1)
		}

	}()
	time.Sleep(2 * time.Second)
	for i := 0; i < 3; i++ {
		num := <-ch
		fmt.Println("主协程recv数据：", num)
	}
	fmt.Println("主线程结束~", time.Since(now))

}
func testNoBuffer03() {
	var ch chan int = make(chan int)
	fmt.Printf("len=%d cap=%d\n", len(ch), cap(ch))
	now := time.Now()

	go func() {
		for i := 0; i < 3; i++ {
			ch <- i
		}
		close(ch) // 关闭channel后不能再写数据
		//ch <- 111

	}()
	for {
		if num, ok := <-ch; ok {
			fmt.Println("num=", num)
		} else {
			fmt.Println("channel is closed")
			break
		}
	}

	fmt.Println("主线程结束~", time.Since(now))

}
func testNoBuffer04() {
	var ch chan int = make(chan int)
	fmt.Printf("len=%d cap=%d\n", len(ch), cap(ch))
	now := time.Now()

	go func() {
		for i := 0; i < 3; i++ {
			ch <- i
		}
		close(ch)

	}()
	//使用for range ，使用前必须关闭channel,否则：fatal error: all goroutines are asleep - deadlock!
	for num := range ch {
		fmt.Println("num=", num)
	}

	fmt.Println("主线程结束~", time.Since(now))
}

func testNoBuffer05() {
	var ch chan int = make(chan int)
	fmt.Printf("len=%d cap=%d\n", len(ch), cap(ch))

	go func() {
		for i := 0; i < 3; i++ {
			ch <- i
		}
		close(ch)

	}()

	for {
		select {
		case num, ok := <-ch:
			if !ok {
				fmt.Println("channel is closed")
				return
			}
			fmt.Println("num=", num)
		case <-time.After(time.Second * 5): //不关闭chan,则一定等到5s后，time out
			fmt.Println("time out")
			return
		}
	}

}

func testWithBuffer() {
	ch := make(chan string, 3)

	go func() {
		for i := 0; i < 5; i++ {
			ch <- fmt.Sprintf("[ele-%d]", i)
			fmt.Println("send", i)
		}
	}()
	time.Sleep(time.Second * 2)
	for i := 0; i < 5; i++ {
		fmt.Println("recv", <-ch)
	}

}
func testWithBuffer01() {
	ch := make(chan string, 3)

	go func() {
		for i := 0; i < 5; i++ {
			ch <- fmt.Sprintf("[ele-%d]", i)
			fmt.Println("send", i)
		}
	}()
	time.Sleep(time.Second * 2)
	for i := 0; i < 5; i++ {
		fmt.Println("recv", <-ch)
	}

}
